<!-- 标注页面 -->
<template>
  <div>
    <div v-if="!edit" ref="html2canvas" id="qaOnline" style="position: relative; background-color: Gainsboro">
      <el-card>
        <el-row>
          <el-col :span="23" :xs="24">
            <el-form :inline="true" label-width="90px">
              <!-- 验证状态 -->
              <el-form-item
                :label="'验收状态：'"
                :label-position="'left'"
                style="margin-top: -5px; margin-bottom: -30px">
                <el-tag>{{ currentStatus }}</el-tag>
              </el-form-item>
              <!-- 批注输入框 -->
              <el-form-item style="margin-top: -5px; margin-bottom: -30px">
                <el-input id="remarkInput" type="text" placeholder="批注" size="mini" v-model="remark"/>
              </el-form-item>
              <!-- 通过 按钮 -->
              <el-form-item style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip effect="dark" content="通过" placement="right-end">
                  <el-button type="success" size="mini" @click="handleComments('通过')" icon="el-icon-check" circle/>
                </el-tooltip>
              </el-form-item>
              <!-- 驳回 按钮 -->
              <el-form-item style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip effect="dark" content="驳回" placement="right-end">
                  <el-button type="danger" size="mini" @click="handleComments('驳回')" icon="el-icon-close" circle/>
                </el-tooltip>
              </el-form-item>
              <!-- 挂起 按钮 -->
              <el-form-item style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip effect="dark" content="挂起" placement="right-end">
                  <el-button
                    type="warning"
                    size="mini"
                    @click="handleComments('挂起')"
                    icon="el-icon-sort-down"
                    circle
                  />
                </el-tooltip>
              </el-form-item>
              <!-- 全屏 -->
              <el-form-item style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip effect="dark" content="全屏" placement="right-end">
                  <el-button
                    v-if="!isFullscreen"
                    type="primary"
                    size="mini"
                    @click="threejsFullScreen()"
                    icon="el-icon-full-screen"
                    circle
                  />
                </el-tooltip>
                <el-tooltip effect="dark" content="退出全屏" placement="right-end">
                  <el-button
                    v-if="isFullscreen"
                    type="primary"
                    size="mini"
                    @click="threejsFullScreen()"
                    icon="el-icon-aim"
                    circle
                  />
                </el-tooltip>
              </el-form-item>
              <!-- TrackId -->
              <el-form-item v-if="markType !== 10" style="margin-top: -5px; margin-bottom: -30px">
                <el-input id="trackID" type="text" placeholder="TrackID" size="mini" v-model="selectedObject.a1"/>
              </el-form-item>
              <!-- 查找TrackId 按钮-->
              <el-form-item v-if="markType !== 10" style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip effect="dark" content="查找TrackId" placement="right-end">
                  <el-button
                    type="primary"
                    size="mini"
                    @click="sync_highlight_objects('', selectedObject, undefined)"
                    icon="el-icon-search"
                    circle
                  />
                </el-tooltip>
              </el-form-item>
              <!-- 批注列表 -->
              <el-form-item style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip effect="dark" content="批注列表" placement="right-end">
                  <el-button
                    type="primary"
                    size="mini"
                    @click="
                      () => {
                        remarkListVisable = !remarkListVisable
                        this.$refs.remarkList.show(remarkListVisable)
                      }
                    "icon="el-icon-notebook-2"
                    circle
                  />
                </el-tooltip>
              </el-form-item>
              <!-- 融合浏览 -->
              <el-form-item v-show="radarView" style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip effect="dark" content="融合浏览" placement="right-end">
                  <el-button
                    type="primary"
                    size="mini"
                    @click="
                      () => {
                        $router.push({
                          path: '/mark/RadarView',
                          query: {
                            taskId: queryParams.taskId,
                            mQaResultId: fileList[currentIndex].mQaResultId,
                          },
                        })
                      }
                    "
                    icon="el-icon-video-camera-solid"
                    circle
                  />
                </el-tooltip>
              </el-form-item>
              <!-- 语义分割标注工具 -->
              <el-form-item style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip v-show="labelTools['split']" effect="dark" content="语义分割标注工具" placement="right-end">
                  <el-button type="primary" size="mini" @click="enterEditPage()" icon="el-icon-edit" circle/>
                </el-tooltip>
              </el-form-item>
              <!-- 标注员 -->
              <el-form-item
                v-if="fileList[currentIndex] && fileList[currentIndex].updateBy && !checkrole(['qa'])"
                :label="'标注员：'"
                :label-position="'left'"
                style="margin-top: -5px; margin-bottom: -30px"
              >
                {{ fileList[currentIndex].updateBy }}
              </el-form-item>
              <!-- 更新时间 -->
              <el-form-item
                v-if="fileList[currentIndex] && fileList[currentIndex].updateTime && !checkrole(['qa'])"
                :label="'更新时间：'"
                :label-position="'left'"
                style="margin-top: -5px; margin-bottom: -30px"
              >
                {{ fileList[currentIndex].updateTime }}
              </el-form-item>
            </el-form>
          </el-col>
          <el-col :span="1" :xs="24">
            <!-- 返回文件列表 -->
            <el-form :inline="true" label-width="68px">
              <el-form-item style="margin-top: -5px; margin-bottom: -30px">
                <el-tooltip effect="dark" content="返回文件列表" placement="right-end">
                  <el-button type="primary" icon="el-icon-d-arrow-left" size="mini" @click="returnFileList()" circle/>
                </el-tooltip>
              </el-form-item>
            </el-form>
          </el-col>
        </el-row>
      </el-card>
      <div style="position: relative; height: 83vh">
        <!-- 点云：三维 -->
        <point-cloud
          ref="pointCloud"
          v-if="markType !== 10"
          v-bind:height="83"
          v-bind:task-id="queryParams.taskId"
          v-bind:hide-tip="HideTip"
          v-bind:show-tip="ShowTip"
          v-bind:attribute-names="attributeNames"
          v-bind:render-type="renderType"
          v-bind:camera-position="cameraPosition"
          v-bind:high-light-cube-points="highLightCubePoints"
          v-bind:color-names="colorNames"
          v-bind:is-loading="isLoading"
          v-bind:loading="loading"
          v-bind:sync_highlight_objects="sync_highlight_objects"
          v-bind:sync_clear_highlight_objects="sync_clear_highlight_objects"
          v-bind:change-page="changePage"
          v-bind:set-position="setPosition"
          v-bind:elements-remark="elementsRemark"
          v-bind:handle-element-comments="remarkFormOpen"
          v-bind:change-cube-info="changeCubeInfo"
          v-bind:add-split-mark-annotation="addSplitMarkAnnotation"
          v-bind:add-mark-annotation="addMarkAnnotation"
          v-bind:image-projection="imageProjection">
        </point-cloud>
        <!-- 图片：二维 -->
        <div id="image-view">
          <picture-list
            ref="pictureList"
            v-if="markType !== 9"
            v-bind:height="83"
            v-bind:task-id="queryParams.taskId"
            v-bind:hide-tip="HideTip"
            v-bind:show-tip="ShowTip"
            v-bind:attribute-names="attributeNames"
            v-bind:color-names="colorNames"
            v-bind:sync_highlight_objects="sync_highlight_objects"
            v-bind:sync_clear_highlight_objects="sync_clear_highlight_objects"
            v-bind:set-position="setPosition"
            v-bind:elements-remark="elementsRemark"
            v-bind:handle-element-comments="remarkFormOpen"
            v-bind:change-cube-info="changeCubeInfo"
            v-bind:change-list="changeList"
            v-bind:add-pic-mark-annotation="addPicMarkAnnotation"
            v-bind:submit-annotations="submitAnnotations"
          />
        </div>
      </div>

      <!-- 底部 -->
      <div id="bottomDiv" class="bottom-div">
        <!-- 进度条 -->
        <el-progress
          :percentage="cachePercentage"
          color="blue"
          v-show="cachePercentage > 0 && cachePercentage < 100"
          status="exception">
        </el-progress>
        <el-row :gutter="20">
          <!-- 任务名称 -->
          <el-col :span="8" :xs="24">
            <el-form :inline="true">
              <el-form-item style="display: table-cell; width: 100%; text-align: left">
                <div class="filename">
                  <span>{{ taskPath }}</span>
                </div>
              </el-form-item>
            </el-form>
          </el-col>
          <!-- 底部 -->
          <el-col :span="8" :xs="24">
            <el-form align="center">
              <el-form-item style="">
                <!-- 开始播放 -->
                <el-button
                  v-if="!playStarted"
                  :disabled="cacheStatus.cacheIndex < currentIndex - 30"
                  type="primary"
                  size="mini"
                  @click="startPlay()"
                  icon="el-icon-caret-right"
                  circle
                />
                <!-- 结束播放 -->
                <el-button
                  v-if="playStarted"
                  type="primary"
                  size="mini"
                  @click="pausePlay()"
                  icon="el-icon-video-pause"
                  circle
                />
                <!-- 上一页 -->
                <el-button
                  type="primary"
                  size="mini"
                  :disabled="loading || currentIndex <= 0"
                  @click="changePage(-1)"
                  icon="el-icon-back"
                  circle
                />
                <span
                >&nbsp;&nbsp;&nbsp;&nbsp;当前：({{ currentIndex + 1 }} /
                  {{ fileList.length }})&nbsp;&nbsp;&nbsp;&nbsp;</span
                >
                <!-- 下一页 -->
                <el-button
                  type="primary"
                  size="mini"
                  :disabled="loading || currentIndex >= fileList.length - 1"
                  @click="changePage(1)"
                  icon="el-icon-right"
                  circle
                />
                &nbsp;
                <el-select
                  :value="currentIndex + 1"
                  @change="
                    (value) => {
                      changePage(value - 1 - currentIndex)
                    }
                  "style="width: 80px"
                >
                  <el-option v-for="(item, index) in fileList" :key="item.fileId" :label="index + 1" :value="index + 1">
                  </el-option>
                </el-select>
              </el-form-item>
            </el-form>
          </el-col>
          <!-- 标注列表、属性色块 -->
          <el-col :span="8" :xs="24">
            <el-form :inline="true">
              <el-form-item style="display: table-cell; width: 100%; text-align: right">
                <div class="filename">
                  <span v-if="fileList[currentIndex]">{{ fileList[currentIndex].fileId }}&nbsp;</span>
                </div>
              </el-form-item>
              <!-- 标注物体列表 -->
              <el-form-item style="display: table-cell">
                <el-button
                  @click="
                    annotationDialogVisible = true
                    queryAnnotationList()
                  "
                  type="text"
                >标注列表
                </el-button>
              </el-form-item>
              <el-form-item style="display: table-cell">
                <el-popover
                  placement="top-end"
                  width="360"
                  :visible-arrow="false"
                  trigger="click"
                  @show="showColorDialogVar = true"
                  @hide="showColorDialogVar = false"
                >
                  <div>
                    <div id="colorPanel" class="icon-list">
                      <div>
                        <p>属性色块：</p>
                      </div>
                      <div class="color-name" v-for="dict in colorNames" :key="dict.dictValue">
                        <svg :style="'height: 18px;width: 18px;'">
                          <rect width="18px" height="18px" :style="'fill:' + dict.dictLabel"/>
                        </svg>
                        <span>{{ getLabelName(dict.dictValue) }} </span>
                      </div>
                    </div>
                  </div>
                  <el-button slot="reference" type="text" :disabled="isFullscreen" class="color-name-btn">
                    色块
                    <i
                      style="transform: rotate(90deg)"
                      :class="showColorDialogVar ? 'el-icon-d-arrow-right' : 'el-icon-d-arrow-left'"
                    ></i>
                  </el-button>
                </el-popover>
              </el-form-item>
            </el-form>
          </el-col>
        </el-row>
      </div>

      <!-- 标注目标对话框 -->
      <el-dialog
        v-dialogDrag
        :title="'标注目标列表'"
        :visible.sync="annotationDialogVisible"
        :fullscreen="annotationDialogFullScreen"
        :close-on-click-modal="false"
        :show-close="true"
        width="50%"
        center
      >
        <template slot="title">
          <div class="avue-crud__dialog__header">
            <span class="el-dialog__title">
              <span
                style="
                  display: inline-block;
                  background-color: #3478f5;
                  width: 3px;
                  height: 20px;
                  margin-right: 5px;
                  float: left;
                  margin-top: 2px;
                "
              ></span>
              标注目标列表
            </span>
            <div class="avue-crud__dialog__menu" @click="annotationDialogFullScreen = !annotationDialogFullScreen">
              <i class="el-icon-full-screen"></i>
            </div>
          </div>
        </template>
        <div>
          <el-row :gutter="10" class="mb8">
            <el-col :span="1.5">
              <el-button
                type="danger"
                @click="handleAnnotationDelete"
                icon="el-icon-delete"
                size="mini"
                :disabled="multiple"
              >删除
              </el-button
              >
            </el-col>
          </el-row>
          <el-table
            @row-click="onAnnotationRowSelect"
            :data="annotationList"
            @selection-change="handleSelectionChange"
            ref="fileTable"
            style="max-height: 75vh; overflow: auto"
          >
            <el-table-column type="selection" width="55" align="center"/>
            <el-table-column
              label="格式"
              align="center"
              width="80px"
              prop="fileType"
              :formatter="
                (row) => {
                  return row.fileType == '2d' ? '二维' : '三维'
                }
              "
            />
            <el-table-column label="类别" align="left" width="120px" prop="name" :formatter="annotationNameFormatter"/>
            <el-table-column label="操作" align="center" width="160px" class-name="small-padding fixed-width">
              <template slot-scope="scope">
                <el-button size="mini" type="text" icon="el-icon-document" @click="handleAnnotationUpdate(scope.row)"
                >修改
                </el-button
                >
                <el-button size="mini" type="text" icon="el-icon-delete" @click="handleAnnotationDelete(scope.row)"
                >删除
                </el-button
                >
              </template>
            </el-table-column>
            <el-table-column
              label="属性a1"
              align="left"
              width="75px"
              prop="a1"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性a2"
              align="left"
              width="75px"
              prop="a2"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性a3"
              align="left"
              width="75px"
              prop="a3"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性a4"
              align="left"
              width="75px"
              prop="a4"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性a5"
              align="left"
              width="75px"
              prop="a5"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性a6"
              align="left"
              width="75px"
              prop="a6"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性a7"
              align="left"
              width="75px"
              prop="a7"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性a8"
              align="left"
              width="75px"
              prop="a8"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性b1"
              align="left"
              width="75px"
              prop="b1"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性b2"
              align="left"
              width="75px"
              prop="b2"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性b3"
              align="left"
              width="75px"
              prop="b3"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性b4"
              align="left"
              width="75px"
              prop="b4"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性b5"
              align="left"
              width="75px"
              prop="b5"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性b6"
              align="left"
              width="75px"
              prop="b6"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性b7"
              align="left"
              width="75px"
              prop="b7"
              :formatter="annotationAttributeFormatter"
            />
            <el-table-column
              label="属性b8"
              align="left"
              width="75px"
              prop="b8"
              :formatter="annotationAttributeFormatter"
            />
          </el-table>
        </div>
      </el-dialog>

      <!-- 添加批注对话框 -->
      <el-dialog append-to-body :title="'目标信息'" :visible.sync="detailsDialogOpen" width="600px">
        <el-form :model="selectedObject" label-position="right" label-width="80px">
          <el-form-item
            v-for="attribute in selectedObject.attributes"
            :key="attribute.key"
            :label="attribute.key + ': '"
          >
            <el-input v-model="attribute.value" maxlength="50" readonly/>
          </el-form-item>
          <el-form-item label="错误类型" prop="errorType">
            <el-select
              v-model="selectedObject.errorType"
              @change="errorTypeSelectChanged"
              placeholder="请选择错误类型"
              clearable
              size="small"
            >
              <el-option
                v-for="dict in errorTypeOptions"
                :key="dict.dictValue"
                :label="dict.dictLabel"
                :value="dict.dictValue"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="目标批注">
            <el-input
              id="detailRemarkInput"
              maxlength="80"
              placeholder="请在此输入针对改目标的批注"
              v-model="selectedObject.remark"
            />
          </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button
            type="primary"
            @click="
              handleElementComments(
                selectedObject.a1 ? selectedObject.a1 + '' : selectedObject.mMarkAnnotationId + '',
                selectedObject.remark
              )
            "
          >提 交
          </el-button
          >
          <el-button @click="cancelHandleElementComments()">取 消</el-button>
        </div>
      </el-dialog>

      <!-- 属性修改对话框 -->
      <el-dialog
        :title="annotationInfoDialogTitle"
        :visible.sync="annotationInfoDialogOpen"
        width="600px"
        append-to-body
        @close="cancelUpdateForm"
      >
        <!-- el-form ref="form" :model="form" :rules="labelRules" label-width="160px"-->
        <el-form ref="form" :model="form" label-width="200px">
          <el-form-item label="应用范围">
            <el-checkbox
              v-model="form.applyFullTask"
              :checked="form.applyFullTask"
              :disabled="form.applyFollowResult"
              label="应用到所有帧"
            ></el-checkbox>
            <el-checkbox
              v-model="form.applyFollowResult"
              :checked="form.applyFollowResult"
              :disabled="form.applyFullTask"
              label="应用到后续帧"
            ></el-checkbox>
          </el-form-item>
          <el-form-item label="类型" prop="name">
            <el-select v-model="form.name" placeholder="请选择类型" @change="annotationNameChanged(form.name)">
              <el-option v-for="(value, key) in formOptions.name" :key="key" :label="value" :value="key"/>
            </el-select>
          </el-form-item>
          <div v-if="selectedObject.type == '3d'">
            <el-form-item v-for="i in 8" :label="formOptions['a' + i + '_3d_description']" :prop="'a' + i" :key="i">
              <el-input
                v-if="
                  formOptions['a' + i + '_3d'] &&
                  Object.getOwnPropertyNames(formOptions['a' + i + '_3d']).length == 0 &&
                  selectedObject.type == '3d' &&
                  formOptions.a1_3d_description
                "
                v-model="form['a' + i]"
                :placeholder="'请选择' + formOptions.a1_3d_description"
                size="mini"
              />
              <el-radio-group
                v-if="
                  formOptions['a' + i + '_3d'] &&
                  Object.getOwnPropertyNames(formOptions['a' + i + '_3d']).length > 0 &&
                  selectedObject.type == '3d' &&
                  formOptions['a' + i + '_3d_description']
                "
                v-model="form['a' + i]"
              >
                <el-radio
                  @click.native.prevent="radioClickitem(key, 'a' + i)"
                  v-for="(value, key) in formOptions['a' + i + '_3d']"
                  :key="key"
                  :label="key"
                  :value="key"
                >{{ value }}
                </el-radio
                >
              </el-radio-group>
            </el-form-item>
          </div>
          <div v-if="selectedObject.type == '2d'">
            <el-form-item v-for="i in 8" :label="formOptions['a' + i + '_2d_description']" :prop="'a' + i" :key="i">
              <el-input
                v-if="
                  formOptions['a' + i + '_2d'] &&
                  Object.getOwnPropertyNames(formOptions['a' + i + '_2d']).length == 0 &&
                  selectedObject.type == '2d' &&
                  formOptions.a1_2d_description
                "
                v-model="form['a' + i]"
                :placeholder="'请选择' + formOptions.a1_2d_description"
                size="mini"
              />
              <el-radio-group
                v-if="
                  formOptions['a' + i + '_2d'] &&
                  Object.getOwnPropertyNames(formOptions['a' + i + '_2d']).length > 0 &&
                  selectedObject.type == '2d' &&
                  formOptions['a' + i + '_2d_description']
                "
                v-model="form['a' + i]"
              >
                <el-radio
                  @click.native.prevent="radioClickitem(key, 'a' + i)"
                  v-for="(value, key) in formOptions['a' + i + '_2d']"
                  :key="key"
                  :label="key"
                  :value="key"
                >{{ value }}
                </el-radio
                >
              </el-radio-group>
            </el-form-item>
          </div>
          <div v-if="selectedObject.type == '3d'">
            <el-form-item v-for="i in 8" :label="formOptions['b' + i + '_3d_description']" :prop="'b' + i" :key="i">
              <el-radio-group
                v-if="
                  formOptions['b' + i + '_3d'] &&
                  Object.getOwnPropertyNames(formOptions['b' + i + '_3d']).length > 0 &&
                  selectedObject.type == '3d' &&
                  formOptions['b' + i + '_3d_description']
                "
                v-model="form['b' + i]"
              >
                <el-radio
                  @click.native.prevent="radioClickitem(key, 'b' + i)"
                  v-for="(value, key) in formOptions['b' + i + '_3d']"
                  :key="key"
                  :label="key"
                  :value="key"
                >{{ value }}
                </el-radio
                >
              </el-radio-group>
            </el-form-item>
          </div>
          <div v-if="selectedObject.type == '2d'">
            <el-form-item v-for="i in 8" :label="formOptions['b' + i + '_2d_description']" :prop="'b' + i" :key="i">
              <el-radio-group
                v-if="
                  formOptions['b' + i + '_2d'] &&
                  Object.getOwnPropertyNames(formOptions['b' + i + '_2d']).length > 0 &&
                  selectedObject.type == '2d' &&
                  formOptions['b' + i + '_2d_description']
                "
                v-model="form['b' + i]"
              >
                <el-radio
                  @click.native.prevent="radioClickitem(key, 'b' + i)"
                  v-for="(value, key) in formOptions['b' + i + '_2d']"
                  :key="key"
                  :label="key"
                  :value="key"
                >{{ value }}
                </el-radio
                >
              </el-radio-group>
            </el-form-item>
          </div>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button type="primary" @click.native.prevent="submitUpdateForm">确 定</el-button>
          <el-button @click="cancelUpdateForm">取 消</el-button>
        </div>
      </el-dialog>

      <!-- 点云分割目标选择对话框 -->
      <el-dialog title="选择待修改目标" :visible.sync="updateSplitInfoDialogOpen" width="480px" append-to-body>
        <el-form ref="updateSplitInfoForm" :model="updateSplitInfoForm" label-width="160px">
          <el-form-item label="类型" prop="name">
            <el-select v-model="updateSplitInfoForm.mMarkAnnotationId" placeholder="请选择类型">
              <el-option
                v-for="item in annotation3dList"
                :key="item.mMarkAnnotationId"
                :label="annotationNameFormatter(item) + '' + item.a1"
                :value="item.mMarkAnnotationId"
              />
            </el-select>
          </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button type="primary" @click="submitUpdateSplitInfoForm">确 定</el-button>
          <el-button @click="cancelUpdateSplitInfoForm">取 消</el-button>
        </div>
      </el-dialog>

      <div id="focus_toolTip" class="special_focus_toolTip" v-html="toolTopbody"/>
      <RemarkList
        ref="remarkList"
        :task-id="queryParams.taskId"
        :set-position="setPosition"
        :delete-remark="deleteRemark"
        :update-remark="updateRemark"
      />
    </div>
    <div v-if="edit" style="height: 100vh">
      <iframe :src="editSrc" frameborder="no" style="width: 100%; height: 100%" scrolling="auto"/>
    </div>
  </div>
</template>

<script>
  import $ from 'jquery'
  import {getMarkAnnotations, pointsCloudDetails, imageFile, pcdBlob} from '@/api/mark/onlineCheck'
  import {
    annotationList,
    addAnnotation,
    updateAnnotation,
    updateAnnotationAttributes,
    deleteAnnotation,
    copyPreviousAnnotation,
  } from '@/api/mark/markAnnotation'
  import {listResult, updateResult, calib} from '@/api/mark/qaresult'
  import {getQaTask} from '@/api/mark/qaTask'
  import screenfull from 'screenfull'
  import {checkRole} from '@/utils/permission'
  import PictureList from './components/PictureList'
  import PointCloud from './components/PointCloud'
  import SliderContainer from './components/SliderContainer'
  import RemarkList from './components/RemarkList'
  import {listRemarkBall, addRemarkBall} from '@/api/mark/remarkBall'
  import {Dictionary} from '@/utils/dictionary'
  import html2canvas from 'html2canvas'
  import * as Whammy from './whammy.js'
  import Cookies from 'js-cookie'

  export default {
    name: 'FuseEditor',
    components: {
      SliderContainer,
      PictureList,
      PointCloud,
      RemarkList,
    },
    computed: {
      markAnnotations() {
        return this.$store.state.markData.markAnnotations
      },
    },
    data() {
      return {
        playCachePromise: undefined,
        playing: false,
        playStarted: false,
        taskPath: '',
        seconds: 0,
        interval: undefined,
        playIndex: 0,
        scaleFactor: undefined,
        showAttributesText: true,
        animationFrameId: undefined,
        mouseDown: false,
        renderEnabled: false,
        pointTextFontSize: 48,
        detailsDialogOpen: false,
        showColorDialogVar: false,
        isFullscreen: false,
        queryParams: {
          taskId: undefined,
          mQaResultId: undefined,
        },
        selectedObject: {
          a1: '',
          remark: '',
          attributes: [],
          type: '',
          imageIndex: '',
          errorType: '',
          mPoint: {x: -1, y: -1, z: -1},
          elementInstance: null,
          position: null,
        },
        cubeInfo: {width: '', height: '', length: ''},
        errorTypeOptions: [],
        currentSelection: {},
        colorNames: {},
        attributeNames: {},
        imgCount: 0,
        markType: 0,
        tipContent: '',
        colorBody: '',
        toolTopbody: '',
        remarkMap: new Map(), // 批注图标
        loading: false,

        currentStatus: '',
        currentIndex: -1,
        fileList: {},
        remark: '',
        elementsRemark: {},
        renderType: '',
        highLightCubePoints: false,
        cameraPosition: null,
        selectedObjectA1: null,
        attrsViewDrawer: false,
        changeList: new Dictionary(),
        annotationInfoDialogTitle: '',
        annotationInfoDialogOpen: false,
        updateSplitInfoDialogOpen: false,
        // 属性修改表单参数
        form: {
          applyFullTask: false,
          applyFollowResult: false,
          mMarkAnnotationId: undefined,
          mQaResultId: undefined,
          fileName: undefined,
          name: undefined,
          a1: undefined,
          a2: undefined,
          a3: undefined,
          a4: undefined,
          a5: undefined,
          a6: undefined,
          a7: undefined,
          a8: undefined,
          b1: undefined,
          b2: undefined,
          b3: undefined,
          b4: undefined,
          b5: undefined,
          b6: undefined,
          b7: undefined,
          b8: undefined,
          labels: undefined,
        },
        labelRules: {
          name: [{required: true, trigger: 'blur', message: '类型不能为空'}],
        },
        updateSplitInfoForm: {
          mMarkAnnotationId: undefined,
        },
        formOptions: {},
        remarkListVisable: false,
        cacheStatus: {
          taskId: null,
          cacheIndex: 0,
          started: false,
        },
        cacheStatusVersion: 0,
        cachePercentage: 0,
        lastPlayTime: null,
        hideOther: false,
        radarView: false,
        autoAnnotation: false,
        encoder: null,
        annotationListVisible: false,
        annotationList: null,
        annotation3dList: null,
        annotationTotal: 0,
        annotationQueryParams: {
          mQaResultId: undefined,
        },
        splitMap: new Map(),
        annotationDialogVisible: false,
        annotationDialogFullScreen: false,
        annotationDialogMinimize: false,
        multiple: true,
        ids: null,
        edit: false,
        editSrc: '',
        labelTools: {
          line: false,
          rect: false,
          poly: false,
          rectPoint1: false,
          point1: false,
          split: false,
        },
        fontSize: 14,
      }
    },
    methods: {
      checkrole(role) {
        return checkRole(role)
      },
      // 批注列表点击后图片和点云矩形缩放定位
      setPosition(a1, mQaResultId, remark, type, imageIndex, errorType, point, position) {
        if (!a1 && !position) return
        this.selectedObjectA1 = a1
        if (this.$route.query.index) {
          if (parseInt(this.$route.query.index) - this.currentIndex - 1 != 0)
            this.changePage(parseInt(this.$route.query.index) - this.currentIndex - 1)
        }
        if (this.markType === 10) return
        this.selectedObject.a1 = a1
        this.selectedObject.remark = remark
        this.selectedObject.type = type
        this.selectedObject.imageIndex = imageIndex
        this.selectedObject.errorType = errorType
        this.selectedObject.position = position
        if (type == '2d') {
          this.selectedObject.attributes = this.$refs.pictureList.getSelectedObjectAttributes(a1, imageIndex)
        } else if (type == '3d') {
          this.selectedObject.attributes = this.$refs.pointCloud.getSelectedObjectAttributes(a1)
        }
        this.sync_highlight_objects('', this.selectedObject)
      },
      // 批注列表删除批注后更新图片和点云显示的批注图标
      deleteRemark(a1, type, elementsRemarkKey) {
        this.removeCache(this.fileList[this.currentIndex].mQaResultId)
        this.changePage(0)
        // 这里处理重新打开批注弹框时的remark input值
        // if (this.selectedObject.a1 == a1 && type && this.selectedObject.type == type) {
        //   this.selectedObject.remark = ''
        // }

        // // 删除 this.elementsRemark 对应的记录
        // let item = this.remarkMap.get(elementsRemarkKey);
        // if (item && type == '2d') {
        //   item.remove();
        //   item.markRemarkId && item.textObject.remove();
        // }

        // this.elementsRemark[elementsRemarkKey] = null;
        // this.elementsRemark['ball-' + elementsRemarkKey] = null;
        // this.remarkMap.delete(elementsRemarkKey);
        // if(type === "3d")
        //   this.$refs.pointCloud.reRender();
        // if(type === "2d")
        //   this.$refs.pictureList.reRender();
      },
      // 批注列表更新批注后更新缓存批注数据
      updateRemark(a1, type, elementsRemarkKey, remark) {
        // 这里处理重新打开批注弹框时的remark input值
        if (this.selectedObject.a1 == a1 && type && this.selectedObject.type == type) {
          this.selectedObject.remark = remark
        }

        this.elementsRemark[elementsRemarkKey] = remark
        if (this.elementsRemark['ball-' + elementsRemarkKey]) {
          this.elementsRemark['ball-' + elementsRemarkKey].remark = remark
        }

        // if(type === "3d")
        //   this.$refs.pointCloud.reRender();
        // if(type === "2d")
        //   this.$refs.pictureList.reRender();
      },
      errorTypeSelectChanged(value) {
        // for (let i = 0; i < this.errorTypeOptions.length; i++) {
        //   if (this.errorTypeOptions[i].dictValue === value) {
        //     this.selectedObject.remark = this.errorTypeOptions[i].dictLabel
        //     return
        //   }
        // }
        // this.selectedObject.remark = '验'
      },
      remarkFormOpen(missId, selectedObject) {
        this.selectedObject = selectedObject
        if (this.selectedObject) {
          this.HideTip()
          this.selectedObject.errorType = null
          this.detailsDialogOpen = true
          this.selectedObject.remark = ''
          let detailRemarkInput = document.getElementById('detailRemarkInput')
          if (detailRemarkInput) detailRemarkInput.focus()
        }
      },
      // 更新批注信息（新增或删除批注）
      handleElementComments(id, remark) {
        if (!this.checkrole(['qa'])) {
          if (!this.selectedObject.errorType) {
            alert('请选择错误类型')
            return
          }
        }
        let remarkBall = {
          taskId: this.fileList[this.currentIndex].taskId,
          mQaResultId: this.fileList[this.currentIndex].mQaResultId,
          fileName: this.fileList[this.currentIndex].fileId,
          trackId: id,
          mType:
            this.selectedObject.type + (this.selectedObject.type == '2d' ? '-' + this.selectedObject.imageIndex : ''),
          errorType: this.selectedObject.errorType,
          remark: remark,
          x: this.selectedObject.mPoint.x,
          y: this.selectedObject.mPoint.y,
          z: this.selectedObject.mPoint.z,
        }
        addRemarkBall(remarkBall).then((response) => {
          if (response.code === 200) {
            if (this.selectedObject.callback) {
              this.selectedObject.callback('success', response.markRemarkId)
            }
            if (this.selectedObject.elementInstance)
              this.selectedObject.elementInstance.markRemarkId = response.markRemarkId
            // if(this.markType === 10) {
            this.removeCache(this.fileList[this.currentIndex].mQaResultId)
            this.changePage(0)
            this.remarkListVisable = false
            this.$refs.remarkList.show(this.remarkListVisable)
            // }
            // this.msgSuccess("更新成功");
          } else {
            this.msgError(response.msg)
            if (this.selectedObject.callback) {
              this.selectedObject.callback('fail')
            }
          }
        })
        this.detailsDialogOpen = false
      },
      cancelHandleElementComments() {
        this.detailsDialogOpen = false
        if (this.selectedObject.callback) {
          this.selectedObject.callback('cancel')
        }
      },
      // 验收提交
      handleComments(ret) {
        this.fileList[this.currentIndex].mQaResult = ret
        this.fileList[this.currentIndex].remark = this.remark
        let data = {
          taskId: this.fileList[this.currentIndex].taskId,
          fileId: this.fileList[this.currentIndex].fileId,
          markResultId: this.fileList[this.currentIndex].markResultId,
          markType: this.fileList[this.currentIndex].markType,
          mQaResultId: this.fileList[this.currentIndex].mQaResultId,
          mQaResult: this.fileList[this.currentIndex].mQaResult,
          createBy: this.fileList[this.currentIndex].createBy,
          createTime: this.fileList[this.currentIndex].createTime,
          updateBy: this.fileList[this.currentIndex].updateBy,
          updateTime: this.fileList[this.currentIndex].updateTime,
          remark: this.fileList[this.currentIndex].remark,
        }
        updateResult(data).then((response) => {
          if (response.code === 200) {
            if (ret == '') {
              this.msgSuccess('批注更新成功。')
            } else if (this.currentIndex < this.fileList.length - 1) {
              this.changePage(1)
              this.msgSuccess('标注结果' + ret + '，开始载入下一张。')
            } else {
              this.msgSuccess('标注结果' + ret + '，已到达最后一张。')
            }
          } else {
            this.msgError(response.msg)
          }
        })
      },
      // 翻页函数，上一页、下一页翻页，页码跳转、选中批注后跳转页码
      changePage(num, playModel = false) {
        if (this.changeList.count() > 0) {
          this.$confirm('当前页面存在未保存的数据，是否忽略所做的修改?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'email',
          })
            .then(() => {
              this.changePage1(num, playModel)
            })
            .catch(function () {
            })
        } else {
          this.changePage1(num, playModel)
        }
      },
      changePage1(num, playModel = false) {
        console.debug('start change page.')
        this.changeList.clear()
        cancelAnimationFrame(this.animationFrameId)

        if (this.currentIndex + num < 0 || this.currentIndex + num >= this.fileList.length) {
          return
        }
        this.currentIndex += num

        if (this.cacheStatus && this.cacheStatus.cacheIndex <= this.currentIndex /*&& !this.cacheStatus.started*/) {
          this.cacheStatus.cacheIndex = this.currentIndex - 1
          let getAllKeysPromise = new Promise((resolve, reject) => {
            this.$getAllKeys((allkeys) => {
              resolve(allkeys)
            })
          })
          getAllKeysPromise.then((ret) => {
            this.cacheStatusVersion++
            this.pcdCache(this.$route.query.taskId, ret)
          })
        }

        this.remark = this.fileList[this.currentIndex].remark
        let query = {
          taskId: this.queryParams.taskId,
          mQaResultId: this.fileList[this.currentIndex].mQaResultId,
        }

        this.$router.replace({path: '/mark/editor2d', query: query})

        this.currentStatus = this.fileList[this.currentIndex].mQaResult
          ? this.fileList[this.currentIndex].mQaResult
          : '待验收'
        this.$store.dispatch('mqaResultCurrentIndexCached', this.currentIndex)

        if (parseInt(this.markType) !== 10) {
          this.$refs.pointCloud.getPointsCloud(
            this.fileList,
            this.currentIndex,
            this.fileList[this.currentIndex].mQaResultId,
            playModel,
            this.showAttributesText
          )
        }
        if (this.imgCount > 0) {
          this.$refs.pictureList.loadDrawing(
            this.currentIndex,
            this.fileList[this.currentIndex].mQaResultId,
            this.showAttributesText
          )
        }
      },
      cacheFile(qaResultId) {
        const readValue = this.$store.state.markData.markAnnotations['MA:' + qaResultId]
        if (!readValue) {
          pointsCloudDetails(qaResultId).then((res) => {
            if (res.fileType === 'pcd') {
              this.$store.state.markData.markAnnotations.set('MA:' + qaResultId, res.annotation)
            }
          })
        } else {
          console.debug(qaResultId, ' exist.')
        }
      },
      removeCache(qaResultId) {
        this.markAnnotations.delete('MA:' + qaResultId + '')
        // this.$removeItem("MA:" + qaResultId + "");
        if (this.imgCount === 1) {
          this.markAnnotations.delete('MA:' + qaResultId + ':img')
          // this.$removeItem("MA:" + qaResultId + ":img");
        } else if (this.imgCount !== 0) {
          for (let j = 0; j < this.imgCount; j++) {
            this.markAnnotations.delete('MA:' + qaResultId + ':img' + (j + 1))
            // this.$removeItem("MA:" + qaResultId + ":img:" + (j + 1));
          }
        }
      },
      markListClick(trackId) {
        this.selectedObject.a1 = trackId
        this.sync_highlight_objects('', this.selectedObject)
      },
      // 页面全屏函数
      threejsFullScreen() {
        this.isFullscreen = !this.isFullscreen
        if (this.isFullscreen) {
          try {
            screenfull.request(document.getElementById('qaOnline'))
          } catch (err) {
          }
        } else {
          try {
            screenfull.toggle()
          } catch (err) {
          }
        }
      },
      // 返回到质检结果记录列表页面
      returnFileList(e) {
        // history.back();
        history.pushState(null, null, document.URL)
        if (e) e.preventDefault()
        this.$router.replace({
          path: '/mark/result',
          query: {taskId: this.queryParams.taskId},
        })
        for (let i = 0; i < this.$store.state.tagsView.visitedViews.length; i++) {
          if (this.$store.state.tagsView.visitedViews[i].name === 'Editor2d') {
            this.$store.dispatch('tagsView/delView', this.$store.state.tagsView.visitedViews[i])
          }
        }
      },
      // 快捷键监听函数
      keyDownHandler(e) {
        if (!e.returnValue) {
          return
        }
        if (
          $(document.activeElement).hasClass('skip-shortcuts') ||
          $(document.activeElement).parent().hasClass('skip-shortcuts')
        ) {
          return
        }
        // enter
        if (document.activeElement.id == 'remarkInput') {
          if (e.keyCode == 13 || e.keyCode == 32) {
            e.preventDefault()
          }
          return
        }
        if (document.activeElement.id == 'detailRemarkInput') {
          if (e.keyCode == 13 || e.keyCode == 32) {
            e.preventDefault()
            if (e.keyCode == 13 && this.selectedObject && this.selectedObject.remark) {
              this.handleElementComments(
                this.selectedObject.a1 ? this.selectedObject.a1 + '' : this.selectedObject.mMarkAnnotationId + '',
                this.selectedObject.remark
              )
            }
          }
          return
        }
        if (document.activeElement.id == 'trackID') {
          if (e.keyCode == 13 && this.selectedObject && this.selectedObject.a1) {
            this.sync_highlight_objects('', this.selectedObject)
          }
        }
        if (e.keyCode == 13) {
          e.preventDefault()
          return
        }
        if (e.altKey && e.ctrlKey) {
          this.showAttributesText = !this.showAttributesText
          this.$refs.pictureList.showAttributesText2D(this.showAttributesText)
          if (this.markType !== 10) this.$refs.pointCloud.showAttributesText2D(this.showAttributesText)
          e.preventDefault()
          return
        }
        if (e.ctrlKey && e.shiftKey) {
          this.hideOther = !this.hideOther
          this.$refs.pictureList.highlight_objects(undefined, this.selectedObject, false, this.hideOther)
          if (this.markType !== 10)
            this.$refs.pointCloud.highlight_objects(undefined, this.selectedObject, false, this.hideOther)
        }
        if (e.ctrlKey && e.key.toLowerCase() === 's') {
          e.preventDefault()
          if (this.$refs.pointCloud) {
            this.$refs.pointCloud.autoSave()
          }
          this.$refs.pictureList.markSubmit()
          return
        }
        if (e.shiftKey && e.key.toLowerCase() === 'v') {
          this.copyPreviousAnnotation()
          return
        }
        if (e.altKey && e.key.toLowerCase() === 'g') {
          e.preventDefault()
          let globalPoint = this.$refs.pictureList.getGlobalAttributes()
          if (globalPoint.mMarkAnnotationId) {
            this.selectedObject = globalPoint
            this.showAttributesChangeForm()
            return
          } else {
            this.addPicMarkAnnotation(globalPoint, globalPoint.callback)
            return
          }
        }

        if (e.key.toLowerCase() === 's') {
          this.$refs.pictureList.paperToolChange('rectPoint1')
          return
        } else if (e.key.toLowerCase() === 'r') {
          this.$refs.pictureList.paperToolChange('rect')
          return
        } else if (e.key.toLowerCase() === 'q') {
          this.$refs.pictureList.paperToolChange('select')
          this.$refs.pointCloud.changeLabelTool('view')
          return
        } else if (e.key.toLowerCase() === 'v') {
          this.$refs.pointCloud.changeLabelTool('verticalLine')
          return
        } else if (e.key.toLowerCase() === 'p') {
          this.$refs.pictureList.paperToolChange('poly')
          return
        } else if (e.key.toLowerCase() === 'l') {
          this.$refs.pictureList.paperToolChange('line')
          return
        } else if (e.key.toLowerCase() === 'o') {
          this.$refs.pictureList.paperToolChange('point1')
          return
        } else if (e.key.toLowerCase() === 'c') {
          this.$refs.pictureList.paperToolChange('ruler')
          return
        }

        // e
        if (e.keyCode == 69) {
          e.preventDefault()
          this.remarkFormOpen(this.selectedObject.a1, this.selectedObject)
        }
        // t
        else if (e.keyCode == 84) {
          e.preventDefault()
          let remarkInput = document.getElementById('remarkInput')
          remarkInput.focus()
        }
          // q
          // else if (e.keyCode == 81) {
          //   history.back()
          // }
        // f
        else if (e.keyCode == 70) {
          if (!this.isFullscreen) {
            this.threejsFullScreen()
          }
        }
        // a
        else if (e.keyCode == 65) {
          if (this.currentIndex >= 1 && this.loading !== true) {
            this.changePage(-1)
          }
        }
        // d
        else if (e.keyCode == 68) {
          if (this.currentIndex < this.fileList.length - 1 && this.loading !== true) {
            this.changePage(1)
          }
        }
          // // s
          // else if(e.keyCode == 83 && this.loading !== true) {
          //   this.handleComments('通过');
          // }
          // // w
          // else if(e.keyCode == 87 && this.loading !== true) {
          //   this.handleComments('驳回');
          // }
          // // r
          // else if(e.keyCode == 82 && this.loading !== true) {
          //   this.handleComments('挂起');
          // }
        // ALT + x
        else if (e.altKey && e.keyCode == 88) {
          this.showAttributesChangeForm()
        }

        // 空格
        if (e.keyCode == 32) {
          this.$refs.pointCloud.startCubeSelection = true
        }
      },
      keyupHandler(e) {
        // 空格
        if (e.keyCode == 32) {
          this.$refs.pointCloud.startCubeSelection = false
        }
      },
      showAttributesChangeForm() {
        let row = this.selectedObject
        this.form.applyFullTask = false
        this.form.applyFollowResult = false
        this.form.mMarkAnnotationId = row.mMarkAnnotationId
        this.form.mQaResultId = row.mQaResultId
        this.form.fileType = row.fileType
        this.selectedObject.type = row.fileType
        this.form.fileName = row.fileName

        let labelTypeName = row.annotationType + '_labelName'
        this.formOptionsInit(row.annotationType + '_', row.name)
        if (this.selectDictLabel(this.attributeNames, labelTypeName)) {
          this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, labelTypeName)).values
        }
        this.form.name = row.name
        if (row.labels) {
          try {
            const attributesJson = JSON.parse(row.labels)
            for (let i = 1; i <= 8; i++) {
              this.form['a' + i] = attributesJson['a' + i]
              this.form['b' + i] = attributesJson['b' + i]
            }
            this.form.labels = attributesJson
          } catch {
            console.log(row.labels, 'parse error')
            for (let i = 1; i <= 8; i++) {
              this.form['a' + i] = row['a' + i]
              this.form['b' + i] = row['b' + i]
            }
          }
        } else {
          for (let i = 1; i <= 8; i++) {
            this.form['a' + i] = row['a' + i]
            this.form['b' + i] = row['b' + i]
          }
        }
        this.form.callback = (params) => {
          if (params.ret === 'confirm') {
            this.annotationDialogVisible = false
          }
        }
        this.annotationInfoDialogOpen = true
      },
      isLoading(loading) {
        this.loading = loading
      },
      // 查询验收任务信息，包含属性类型、颜色类型等基础字典数据
      async qaTaskQuery() {
        let splitLine
        await getQaTask(this.queryParams.taskId).then(async (response) => {
          this.taskPath = response.data.taskName
          if (response.data.taskName.startsWith('0.')) {
            splitLine = parseFloat(response.data.taskName)
          }
          if (response.data && response.data.parentId !== 0) {
            await getQaTask(response.data.parentId).then(async (response) => {
              if (response.data) {
                this.taskPath = response.data.taskName + '@' + this.taskPath
                if (response.data.taskName.startsWith('0.')) {
                  splitLine = parseFloat(response.data.taskName)
                }
                if (response.data.parentId !== '0') {
                  await getQaTask(response.data.parentId).then(async (response) => {
                    if (response.data) {
                      this.taskPath = response.data.taskName + '@' + this.taskPath
                      if (response.data.taskName.startsWith('0.')) {
                        splitLine = parseFloat(response.data.taskName)
                      }
                    }
                  })
                }
              }
            })
          }
        })
        const readValue = this.$store.state.markData.markAnnotations['QaTask:' + this.queryParams.taskId]
        if (readValue) {
          this.$getItem(readValue.data.markAttributes, (err, attributes) => {
            if (attributes) {
              this.attributeNames = attributes
              this.formOptionsInit()
              if (splitLine) {
                let _data = {
                  dictValue: 'splitLine',
                  dictLabel: splitLine,
                }
                this.attributeNames.push(_data)
              }
              this.radarView = this.selectDictLabel(this.attributeNames, 'radarView')
              this.autoAnnotation = this.selectDictLabel(this.attributeNames, 'autoAnnotation')
              this.renderType = this.selectDictLabel(this.attributeNames, 'renderType')
              this.cameraPosition = this.selectDictLabel(this.attributeNames, 'cameraPosition')
              this.highLightCubePoints = this.selectDictLabel(this.attributeNames, 'highLightCubePoints')
              if (this.selectDictLabel(this.attributeNames, 'labelTools')) {
                let labelTools = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelTools'))
                labelTools.forEach((element) => {
                  this.labelTools[element] = true
                })
              }
              this.markType = parseInt(readValue.data.markType)
              if (this.markType === 10) {
                document.getElementById('image-view').style.width = '100%'
                document.getElementById('image-view').style['max-width'] = '100%'
              } else {
                console.log('create', Cookies.get('imageViewSize'))
                document.getElementById('image-view').style.width = Cookies.get('imageViewSize')
              }
              this.imgCount = this.markType == 9 ? 0 : this.markType == 10 ? 1 : this.markType
              this.showColorDialogVar = this.imgCount <= 1
              if (this.selectDictLabel(this.attributeNames, 'FontSize')) {
                this.fontSize = parseInt(this.selectDictLabel(this.attributeNames, 'FontSize'))
              }
              this.$refs.pictureList.initPaperToolPosition(this.imgCount, this.markType, this.fontSize)
              this.getListResult()
            } else {
              this.getDicts(readValue.data.markAttributes).then((res1) => {
                this.attributeNames = res1.data
                this.formOptionsInit()
                this.radarView = this.selectDictLabel(this.attributeNames, 'radarView')
                this.autoAnnotation = this.selectDictLabel(this.attributeNames, 'autoAnnotation')
                this.renderType = this.selectDictLabel(this.attributeNames, 'renderType')
                this.cameraPosition = this.selectDictLabel(this.attributeNames, 'cameraPosition')
                this.highLightCubePoints = this.selectDictLabel(this.attributeNames, 'highLightCubePoints')
                if (this.selectDictLabel(this.attributeNames, 'labelTools')) {
                  let labelTools = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelTools'))
                  labelTools.forEach((element) => {
                    this.labelTools[element] = true
                  })
                }
                this.markType = parseInt(readValue.data.markType)
                if (this.markType === 10) {
                  document.getElementById('image-view').style.width = '100%'
                  document.getElementById('image-view').style['max-width'] = '100%'
                } else {
                  console.log('create', Cookies.get('imageViewSize'))
                  document.getElementById('image-view').style.width = Cookies.get('imageViewSize')
                }
                this.imgCount = this.markType == 9 ? 0 : this.markType == 10 ? 1 : this.markType
                this.showColorDialogVar = this.imgCount <= 1
                if (this.selectDictLabel(this.attributeNames, 'FontSize')) {
                  this.fontSize = parseInt(this.selectDictLabel(this.attributeNames, 'FontSize'))
                }
                this.$refs.pictureList.initPaperToolPosition(this.imgCount, this.markType, this.fontSize)
                this.getListResult()
              })
            }
          })
          this.$getItem(readValue.data.markAttributes + '_colors', (err, attributesColors) => {
            if (attributesColors) {
              this.colorNames = attributesColors
            } else {
              this.getDicts(readValue.data.markAttributes + '_colors').then((res1) => {
                this.colorNames = res1.data
              })
            }
          })
        } else {
          getQaTask(this.queryParams.taskId).then((response) => {
            this.getDicts(response.data.markAttributes).then((res1) => {
              this.attributeNames = res1.data
              this.formOptionsInit()
              if (splitLine) {
                let _data = {
                  dictValue: 'splitLine',
                  dictLabel: splitLine,
                }
                this.attributeNames.push(_data)
              }
              this.radarView = this.selectDictLabel(this.attributeNames, 'radarView')
              this.autoAnnotation = this.selectDictLabel(this.attributeNames, 'autoAnnotation')
              this.renderType = this.selectDictLabel(this.attributeNames, 'renderType')
              this.cameraPosition = this.selectDictLabel(this.attributeNames, 'cameraPosition')
              this.highLightCubePoints = this.selectDictLabel(this.attributeNames, 'highLightCubePoints')
              if (this.selectDictLabel(this.attributeNames, 'labelTools')) {
                let labelTools = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelTools'))
                labelTools.forEach((element) => {
                  this.labelTools[element] = true
                })
              }
              this.markType = parseInt(response.data.markType)
              if (this.markType === 10) {
                document.getElementById('image-view').style.width = '100%'
                document.getElementById('image-view').style['max-width'] = '100%'
              } else {
                console.log('create', Cookies.get('imageViewSize'))
                document.getElementById('image-view').style.width = Cookies.get('imageViewSize')
              }
              this.imgCount = this.markType == 9 ? 0 : this.markType == 10 ? 1 : this.markType
              this.showColorDialogVar = this.imgCount <= 1
              if (this.selectDictLabel(this.attributeNames, 'FontSize')) {
                this.fontSize = parseInt(this.selectDictLabel(this.attributeNames, 'FontSize'))
              }
              this.$refs.pictureList.initPaperToolPosition(this.imgCount, this.markType, this.fontSize)
              this.getListResult()
            })
            this.getDicts(response.data.markAttributes + '_colors').then((res1) => {
              this.colorNames = res1.data
            })
          })
        }
      },
      formOptionsInit(annotationType = undefined, name = undefined) {
        if (annotationType && this.selectDictLabel(this.attributeNames, annotationType + 'labelName')) {
          this.formOptions.name = JSON.parse(
            this.selectDictLabel(this.attributeNames, annotationType + 'labelName')
          ).values
        } else if (name && this.selectDictLabel(this.attributeNames, name + 'labelName')) {
          this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, name + 'labelName')).values
        } else if (this.selectDictLabel(this.attributeNames, 'labelName')) {
          this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelName')).values
        }
        if (this.selectDictLabel(this.attributeNames, 'labelAttributes'))
          this.formOptions.attributes = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelAttributes')).values
        for (let j = 2; j <= 3; j++) {
          for (let i = 1; i <= 8; i++) {
            let tmp = this.selectDictLabel(this.attributeNames, annotationType + 'a' + i + '_' + j + 'd')
            if (!tmp) {
              tmp = this.selectDictLabel(this.attributeNames, name + 'a' + i + '_' + j + 'd')
            }
            if (!tmp) {
              tmp = this.selectDictLabel(this.attributeNames, 'a' + i + '_' + j + 'd')
            }
            if (tmp) {
              try {
                this.formOptions['a' + i + '_' + j + 'd'] = JSON.parse(tmp).values
                this.formOptions['a' + i + '_' + j + 'd_description'] = JSON.parse(tmp).typeDesc
                this.labelRules['a' + i] = [{required: true, trigger: 'blur', message: '不能为空'}]
              } catch {
              }
            }

            tmp = this.selectDictLabel(this.attributeNames, annotationType + 'b' + i + '_' + j + 'd')
            if (!tmp) {
              tmp = this.selectDictLabel(this.attributeNames, name + 'b' + i + '_' + j + 'd')
            }
            if (!tmp) {
              tmp = this.selectDictLabel(this.attributeNames, 'b' + i + '_' + j + 'd')
            }
            if (tmp) {
              try {
                this.formOptions['b' + i + '_' + j + 'd'] = JSON.parse(tmp).values
                this.formOptions['b' + i + '_' + j + 'd_description'] = JSON.parse(tmp).typeDesc
                this.labelRules['b' + i] = [{required: true, trigger: 'blur', message: '不能为空'}]
              } catch {
              }
            }
          }
        }
      },
      // 获取质检结果记录数据列表，并调用图片列表和点云视图的渲染函数进行页面渲染
      getListResult() {
        listResult(this.queryParams).then((response) => {
          this.cachePercentage = 0
          this.fileList = response.rows
          for (let i = 0; i < response.total; i++) {
            if (this.queryParams.mQaResultId == null || this.queryParams.mQaResultId == this.fileList[i].mQaResultId) {
              this.queryParams.mQaResultId = this.fileList[i].mQaResultId
              this.currentIndex = i
              this.currentStatus = this.fileList[this.currentIndex].mQaResult
                ? this.fileList[this.currentIndex].mQaResult
                : '待验收'
              this.remark = this.fileList[this.currentIndex].remark
              this.$store.dispatch('mqaResultCurrentIndexCached', this.currentIndex)
              if (parseInt(this.markType) !== 10) {
                this.$refs.pointCloud.init()
                this.$refs.pointCloud.getPointsCloud(
                  this.fileList,
                  this.currentIndex,
                  this.fileList[i].mQaResultId,
                  false,
                  this.showAttributesText
                )
              }
              if (this.imgCount > 0) {
                if (this.imgCount == 1 || parseInt(this.markType) == 10) this.imgIndex = 0
                else this.imgIndex = 1
                this.$refs.pictureList.loadDrawing(this.currentIndex, this.fileList[i].mQaResultId)
              }
              break
            }
          }

          let getAllKeysPromise = new Promise((resolve, reject) => {
            this.$getAllKeys((allkeys) => {
              resolve(allkeys)
            })
          })

          getAllKeysPromise.then((ret) => {
            this.cacheStatusVersion++
            this.pcdCache(this.$route.query.taskId, ret)
          })

          this.removeAnnotationCache('MA:')
          this.removeAnnotationCache('RM:')
          try {
            getMarkAnnotations(this.$route.query.taskId).then((res) => {
              this.$store.dispatch('markAnnotationsCached', res.annotations)
            })
            listRemarkBall({taskId: this.$route.query.taskId}).then((res) => {
              this.$store.dispatch('remarkListCached', res.rows)
            })
          } catch (e) {
            console.debug('getMarkAnnotations Exception: ' + e)
          }
          this.jumpToBottom()
        })
      },
      async pcdCache(taskId, allkeys) {
        let cacheStatusVersion = this.cacheStatusVersion
        this.cacheStatus.started = true
        this.cacheStatus.taskId = taskId
        // this.cacheStatus.cacheIndex = this.currentIndex;

        while (
          cacheStatusVersion === this.cacheStatusVersion &&
          this.cacheStatus &&
          this.cacheStatus.taskId &&
          this.fileList[this.cacheStatus.cacheIndex]
          ) {
          console.debug('pcdCache version: ', cacheStatusVersion)
          if (this.cacheStatus.cacheIndex < this.currentIndex + 3) {
            let resultId = this.fileList[this.cacheStatus.cacheIndex].mQaResultId
            if (allkeys.indexOf(resultId) != -1) {
              this.cacheStatus.cacheIndex++
              this.cachePercentage = parseInt((this.cacheStatus.cacheIndex * 100) / this.fileList.length)
              continue
            }

            this.cachePercentage = parseInt((this.cacheStatus.cacheIndex * 100) / this.fileList.length)

            await calib({mQaResultId: resultId}).then((response) => {
              let _data = {
                calib: response.calib,
                file_name: 'calib:' + resultId,
              }
              this.$save(_data)
            })

            await pcdBlob(resultId).then((response) => {
              let blob = new Blob([response.data], {
                type: 'application/octet-stream',
              })
              let _data = {
                blob: blob,
                file_name: resultId,
              }
              this.$save(_data)
              if (this.cacheStatus) {
                console.info(
                  '[' + /\d\d\:\d\d\:\d\d/.exec(new Date())[0] + ']',
                  'save ' + this.fileList[this.cacheStatus.cacheIndex].fileId
                )
                this.cacheStatus.cacheIndex++
              }
            })
            try {
              if (this.imgCount === 1) {
                await imageFile(resultId, 0).then((response) => {
                  let imageSrc = response.imageSrc
                  let annotation = response.annotation
                  let _data = {
                    blob: imageSrc,
                    file_name: resultId + ':img',
                  }
                  this.$save(_data)
                  this.markAnnotations.set('MA:' + resultId + ':img', annotation)
                })
              } else {
                for (let j = 0; j < this.imgCount; j++) {
                  await imageFile(resultId, j + 1).then((response) => {
                    let imageSrc = response.imageSrc
                    let annotation = response.annotation
                    let _data = {
                      blob: imageSrc,
                      file_name: resultId + ':img' + (j + 1),
                    }
                    this.$save(_data)
                    this.markAnnotations.set('MA:' + resultId + ':img' + (j + 1), annotation)
                  })
                }
              }
            } catch {
            }
          } else {
            break
          }
        }
        this.cacheStatus.started = false
        this.cachePercentage = parseInt((this.cacheStatus.cacheIndex * 100) / this.fileList.length)
      },
      // 图片列表和点云视图的公共定位缩放函数
      sync_highlight_objects(eventSource, selectedObject, cubeInfo, isZoom = true) {
        this.selectedObject = selectedObject
        this.cubeInfo = cubeInfo
        this.hideOther = false
        this.$refs.pictureList.highlight_objects(eventSource, selectedObject, isZoom, this.hideOther)
        if (this.markType !== 10)
          this.$refs.pointCloud.highlight_objects(eventSource, selectedObject, isZoom, this.hideOther)
      },
      sync_clear_highlight_objects(selectedObject) {
        this.selectedObject = selectedObject
        this.$refs.pictureList.clear_highlight_objects()
        if (this.markType !== 10) this.$refs.pointCloud.clear_highlight_objects()
      },
      // 更新右侧属性信息
      changeCubeInfo(cubeInfo) {
        this.cubeInfo = cubeInfo
      },
      jumpToBottom() {
        document.querySelector('#bottomDiv').scrollIntoView(true)
      },
      HideTip() {
        $('#focus_toolTip').css('display', 'none')
      },
      // 显示标注矩形的属性弹框信息
      ShowTip(message, x, y, tipType = 'tip') {
        if (this.detailsDialogOpen) return
        let focusTooltip = $('#focus_toolTip')
        focusTooltip.css('left', x + 'px')
        focusTooltip.css('top', y + 'px')
        focusTooltip.css('z-index', 9999)
        let attrs = message.split(';')
        let _values
        let pre = ''
        const typeName = attrs[0].split(':')[0]
        let annotationType = undefined
        if (attrs[0].split(':').length === 3) {
          annotationType = attrs[0].split(':')[2]
        }

        try {
          if (this.selectDictLabel(this.attributeNames, typeName + '_labelName')) pre = typeName + '_'
          else if (this.selectDictLabel(this.attributeNames, annotationType + '_labelName')) pre = annotationType + '_'

          if (this.selectDictLabel(this.attributeNames, pre + 'labelName')) {
            let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, pre + 'labelName'))
            _values = jsonObject.values[typeName]
          }
        } catch (e) {
          console.debug(e)
        }
        if (_values == null || _values == undefined || _values == '') _values = typeName
        if (tipType === 'tip') message = '类型：' + _values
        else message = tipType + _values
        message += '<br>'
        let _d = attrs[0].split(':')[1]
        for (let i = 1; i <= 8; i++) {
          if (attrs[i] && attrs[i] != null && attrs[i] != '' && attrs[i] != 'null') {
            pre = ''
            if (this.selectDictLabel(this.attributeNames, typeName + '_a' + i + '_' + _d + 'd')) pre = typeName + '_'
            else if (this.selectDictLabel(this.attributeNames, annotationType + '_a' + i + '_' + _d + 'd'))
              pre = annotationType + '_'
            try {
              let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, pre + 'a' + i + '_' + _d + 'd'))
              let _values = jsonObject.values[attrs[i]]
              if (_values == null || _values == undefined || _values == '') _values = attrs[i]
              message += jsonObject.typeDesc + ': ' + _values + '&nbsp<br>'
            } catch {
              message += attrs[i]
            }
          }
        }
        for (let j = 9; j <= 17; j++) {
          let i = j - 8
          if (attrs[j] && attrs[j] != null && attrs[j] != '' && attrs[j] != 'null' && attrs[j] != 'undefined') {
            pre = ''
            if (this.selectDictLabel(this.attributeNames, typeName + '_b' + i + '_' + _d + 'd')) pre = typeName + '_'
            else if (this.selectDictLabel(this.attributeNames, annotationType + '_b' + i + '_' + _d + 'd'))
              pre = annotationType + '_'
            try {
              let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, pre + 'b' + i + '_' + _d + 'd'))
              let _values = jsonObject.values[attrs[j]]
              if (_values == null || _values == undefined || _values == '') _values = attrs[j]
              message += jsonObject.typeDesc + ': ' + _values + '&nbsp<br>'
            } catch {
              message += attrs[j]
            }
          }
        }
        if (
          this.selectDictLabel(this.attributeNames, 'show3dSize') &&
          this.selectDictLabel(this.attributeNames, 'show3dSize') === 'true'
        ) {
          message += attrs[attrs.length - 1]
        }
        let headerHtml =
          "<div style='font-size:12px; color: #fec443; font-weight: bold; font-family: MicrosoftYaHei;'>" +
          message +
          '</div>'
        let effectHtml = "<div style='font-size:12px;margin-top:3px;' >" + '</div>'
        this.toolTopbody = headerHtml + effectHtml
        focusTooltip.css('display', 'block')
      },
      ShowAttributesText(show) {
        let opacity = show ? 1 : 0
        for (let m = 0; m < this.mainLayer.length; m++) {
          if (!this.mainLayer[m]) continue
          let items = this.mainLayer[m].getItems()
          for (let i = 0; i < items.length; i++) {
            if (items[i].textObject) {
              items[i].textObject.opacity = opacity
            }
          }
        }
      },
      contextmenuHandler(e) {
        e.preventDefault()
      },
      onWindowResize() {
        if (this.$refs.pointCloud) {
          this.$refs.pointCloud.onWindowResize()
        }
        if (this.$refs.pictureList) {
          this.$refs.pictureList.onWindowResize()
        }
      },
      animation() {
        if (this.playStarted) {
          if (performance.now() - this.lastPlayTime > 50) {
            this.playFunction()
          }
          requestAnimationFrame(this.animation)
        }
      },
      startPlay() {
        this.playStarted = true
        this.lastPlayTime = performance.now()
        if (this.interval === undefined) {
          this.interval = requestAnimationFrame(this.animation)
        }
      },
      playFunction() {
        if (this.currentIndex < this.fileList.length) {
          if (this.$store.state.markData.playStatus.pic && this.$store.state.markData.playStatus.pcd) {
            this.$store.state.markData.playStatus.pic = false
            this.$store.state.markData.playStatus.pcd = false
            this.saveImage('html2canvas', 'test')
            let readValue = this.markAnnotations.get('MA:' + this.fileList[this.currentIndex].mQaResultId + '')
            if (readValue) {
              this.$refs.pointCloud
                .getPointsCloud(
                  this.fileList,
                  this.currentIndex,
                  this.fileList[this.currentIndex].mQaResultId,
                  true,
                  this.showAttributesText
                )
                .then(() => {
                  let query = {
                    taskId: this.queryParams.taskId,
                    mQaResultId: this.fileList[this.currentIndex].mQaResultId,
                  }
                  this.$router.replace({
                    path: '/mark/editor2d',
                    query: query,
                  })
                  if (this.imgCount > 0) {
                    this.$refs.pictureList.loadDrawing(
                      this.currentIndex,
                      this.fileList[this.currentIndex].mQaResultId,
                      this.showAttributesText,
                      true
                    )
                  }
                  if (this.currentIndex < this.fileList.length) this.currentIndex++
                  this.lastPlayTime = performance.now()
                })
            }
          }
        } else {
          this.saveImage('html2canvas', 'test')
          this.encoder.compile(false, (output) => {
            const url = (window.webkitURL || window.URL).createObjectURL(output)
            let a = document.createElement('a')
            a.style.display = 'none'
            a.setAttribute('href', url)
            a.setAttribute('download', this.taskName + '_w.mp4')
            document.body.appendChild(a)
            a.click()
            URL.revokeObjectURL(output)
            document.body.removeChild(a)
          })
          this.playStarted = false
          this.currentIndex = this.fileList.length - 1
          cancelAnimationFrame(this.interval)
          this.interval = undefined
        }
      },
      pausePlay() {
        this.playStarted = false
        cancelAnimationFrame(this.interval)
        this.interval = undefined
        this.changePage(0)
      },
      saveChange(annotations) {
        if (annotations) {
          annotations.forEach((annotation) => {
            if (annotation.toDBObject().mQaResultId) {
              addAnnotation(annotation.toDBObject())
            }
          })
        }
        let changeStore = this.changeList.fetch()
        for (let key in changeStore) {
          let tmp = changeStore[key]
          if (tmp.action && tmp.action === 'update') {
            if (tmp.type === 'path' && tmp.info.mMarkAnnotationId && tmp.info.markType === 'rect') {
              let path = tmp.info
              let x = '',
                y = ''
              let tmpPoint = path.pointToLocal(path.point1.segments[0].point)
              x += tmpPoint.x + ';'
              y += tmpPoint.y + ';'
              tmpPoint = path.pointToLocal(path.point3.segments[0].point)
              x += tmpPoint.x + ';'
              y += tmpPoint.y + ';'
              if (path.midPath) {
                tmpPoint = path.pointToLocal(path.midPath.segments[0].point)
                x += tmpPoint.x + ';'
                y += tmpPoint.y + ';'
              }
              if (path.rangePath) {
                tmpPoint = path.pointToLocal(path.rangePath.segments[0].point)
                x += tmpPoint.x + ';'
                y += tmpPoint.y + ';'
                tmpPoint = path.pointToLocal(path.rangePath.segments[1].point)
                x += tmpPoint.x + ';'
                y += tmpPoint.y + ';'
              }
              if (path.rectPoint1) {
                tmpPoint = path.pointToLocal(path.rectPoint1.segments[0].point)
                x += tmpPoint.x + ';'
                y += tmpPoint.y + ';'
              }
              let params = {
                mMarkAnnotationId: path.mMarkAnnotationId,
                x: x.slice(0, x.length - 1),
                y: y.slice(0, y.length - 1),
              }
              updateAnnotation(params)
            } else if (
              tmp.type === 'path' &&
              tmp.info.mMarkAnnotationId &&
              (tmp.info.markType === 'poly' || tmp.info.markType === 'line')
            ) {
              let path = tmp.info
              let x = '',
                y = ''
              for (let i = 0; i < path.segments.length; i++) {
                let tmpPoint = path.pointToLocal(path.segments[i].point)
                x += tmpPoint.x + ';'
                y += tmpPoint.y + ';'
              }
              let params = {
                mMarkAnnotationId: path.mMarkAnnotationId,
                x: x.slice(0, x.length - 1),
                y: y.slice(0, y.length - 1),
              }
              updateAnnotation(params)
            } else if (tmp.type === 'path' && tmp.info.mMarkAnnotationId && tmp.info.markType === 'point1') {
              let path = tmp.info
              let tmpPoint = path.pointToLocal(path.segments[0].point)
              let x = tmpPoint.x + ';'
              let y = tmpPoint.y + ';'
              let params = {
                mMarkAnnotationId: path.mMarkAnnotationId,
                x,
                y,
              }
              updateAnnotation(params)
            } else if (tmp.type === 'path' && tmp.info.mMarkAnnotationId && tmp.info.markType === 'box') {
              let path = tmp.info
              let x = '',
                y = ''
              for (let ii = 1; ii <= 4; ii++) {
                let tmpPoint = path.pointToLocal(path['point' + ii].segments[0].point)
                x += tmpPoint.x + ';'
                y += tmpPoint.y + ';'
              }
              let params = {
                mMarkAnnotationId: path.mMarkAnnotationId,
                x,
                y,
              }
              updateAnnotation(params)
            }
          } else if (tmp.action && tmp.action === 'delete') {
            deleteAnnotation(tmp.info.mMarkAnnotationId)
          } else if (tmp.action && tmp.action === 'addNew') {
            const annotation = tmp.info.toDBObject()
            if (annotation.mQaResultId) {
              addAnnotation(annotation)
            } else {
              this.msgError('页面加载异常，请重新标注。')
            }
          }
          this.changeList.remove(key)
        }
        this.changeList.clear()
        this.removeCache(this.fileList[this.currentIndex].mQaResultId)
        this.changePage(0)
      },
      addSplitMarkAnnotation(pointsIndex, minusPointsIndex, markType, callback) {
        this.$confirm('需要将选中的点作为新目标创建还是更新已有记录？', '提交', {
          confirmButtonText: '新建',
          cancelButtonText: '更新',
          type: 'email',
        })
          .then(() => {
            if (pointsIndex && pointsIndex.length > 0) {
              this.selectedObject = {
                name: '',
                type: '3d',
              }
              this.form.mMarkAnnotationId = null
              this.form.mQaResultId = this.fileList[this.currentIndex].mQaResultId
              this.form.name = this.selectedObject.name
              this.form.annotationType = markType
              this.form.x = pointsIndex.toString()
              this.form.z = markType
              for (let i = 1; i <= 8; i++) {
                this.form['a' + i] = null
                this.form['b' + i] = null
              }
              this.form.fileType = '3d'
              this.form.fileName = this.fileList[this.currentIndex].fileId
              this.form.callback = callback
              this.annotationInfoDialogTitle = '新建点云分割目标'
              this.annotationInfoDialogOpen = true
            }
          })
          .catch(() => {
            this.queryAnnotationList()
            this.updateSplitInfoForm.pointsIndex = pointsIndex
            this.updateSplitInfoForm.minusPointsIndex = minusPointsIndex
            this.updateSplitInfoForm.callback = callback
            this.updateSplitInfoDialogOpen = true
          })
      },
      submitUpdateSplitInfoForm() {
        const formData = this.updateSplitInfoForm
        const tobeUpdated = this.annotationList.find((item) => item.mMarkAnnotationId == formData.mMarkAnnotationId)
        if (!tobeUpdated) {
          this.msgError('请选择要更新的类型')
          return
        }

        let originalPointsIndex = tobeUpdated.x.split(',').map((x) => parseInt(x))
        const removeIndexs = new Set(formData.minusPointsIndex)
        let tmpPoints = originalPointsIndex.filter((item) => !removeIndexs.has(item))
        tmpPoints = [...new Set([...tmpPoints, ...formData.pointsIndex])]

        tobeUpdated.x = tmpPoints.join(',')
        updateAnnotation(tobeUpdated).then((response) => {
          if (response.code == 200) {
            this.updateSplitInfoForm.callback({
              ret: 'confirm',
              form: tobeUpdated,
            })
            this.msgSuccess('更新成功')
            this.removeCache(this.fileList[this.currentIndex].mQaResultId)
            this.changePage(0)
          } else {
            this.msgError(response.msg)
          }
          this.updateSplitInfoDialogOpen = false
        })
      },
      cancelUpdateSplitInfoForm() {
        if (this.updateSplitInfoForm.callback) {
          const params = {
            form: null,
            ret: 'cancel',
          }
          this.updateSplitInfoForm.callback(params)
        }
      },
      addMarkAnnotation(cubeMesh, callback) {
        this.selectedObject.type = '3d'
        this.form.mMarkAnnotationId = null
        this.form.mQaResultId = this.fileList[this.currentIndex].mQaResultId
        this.formOptionsInit('cube_')
        for (let i = 1; i <= 8; i++) {
          this.form['a' + i] = null
          this.form['b' + i] = null
        }
        this.form.fileType = '3d'
        this.form.fileName = this.fileList[this.currentIndex].fileId
        this.form.instance = cubeMesh
        this.form.callback = callback
        this.annotationInfoDialogTitle = '创建点云标注目标（立体框）'
        this.annotationInfoDialogOpen = true
      },
      addPicMarkAnnotation(picMarkAnnotation, callback) {
        this.selectedObject.type = '2d'
        this.form.mMarkAnnotationId = null
        this.form.mQaResultId = this.fileList[this.currentIndex].mQaResultId
        this.form.z = picMarkAnnotation.toDBObject().z
        let labelTypeName = picMarkAnnotation.toDBObject().z + '_labelName'
        this.formOptionsInit(picMarkAnnotation.toDBObject().z + '_')
        if (this.selectDictLabel(this.attributeNames, labelTypeName)) {
          this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, labelTypeName)).values
        }
        for (let i = 1; i <= 8; i++) {
          this.form['a' + i] = null
        }
        for (let i = 1; i <= 8; i++) {
          this.form['b' + i] = null
        }
        this.form.fileType = '2d'
        this.form.fileName = this.fileList[this.currentIndex].fileId
        this.form.instance = picMarkAnnotation
        this.form.callback = callback
        this.annotationInfoDialogTitle = '新建二维标注目标'
        this.annotationInfoDialogOpen = true
      },
      submitAnnotations(annotations) {
        if (this.$refs.pointCloud) {
          this.$refs.pointCloud.autoSave()
        }
        this.saveChange(annotations)
      },
      submitUpdateForm() {
        this.$refs.form.validate((valid) => {
          if (valid) {
            if (this.form.callback) {
              const params = {
                form: this.form,
                ret: 'confirm',
              }
              this.form.callback(params)
            }
            if (!this.form.mMarkAnnotationId) {
              if (this.form.fileType === '3d') {
                if (this.form.z === 'pointLine') {
                  addAnnotation(this.form).then((response) => {
                    if (response.code == 200) {
                      this.msgSuccess('标注成功')
                      this.removeCache(this.fileList[this.currentIndex].mQaResultId)
                      this.changePage(0)
                      this.resetUpdateForm()
                    } else {
                      this.msgError(response.msg)
                      this.resetUpdateForm()
                    }
                  })
                } else if (this.form.z === 'split') {
                  addAnnotation(this.form).then((response) => {
                    if (response.code == 200) {
                      this.msgSuccess('标注成功')
                      this.removeCache(this.fileList[this.currentIndex].mQaResultId)
                      this.changePage(0)
                      this.resetUpdateForm()
                    } else {
                      this.msgError(response.msg)
                      this.resetUpdateForm()
                    }
                  })
                } else {
                  this.form.instance = null
                  this.resetUpdateForm()
                }
              } else if (this.form.fileType === '2d') {
                let rect = this.form.instance
                rect.labelName = this.form.name
                for (let i = 1; i <= 8; i++) {
                  rect['a' + i] = this.form['a' + i]
                  rect['b' + i] = this.form['b' + i]
                }
                this.form.instance = null
                this.resetUpdateForm()
              }
            } else {
              if (this.form.labels) {
                for (let i = 1; i <= 8; i++) {
                  this.form.labels['a' + i] = this.form['a' + i]
                  this.form.labels['b' + i] = this.form['b' + i]
                }
                this.form.labels = JSON.stringify(this.form.labels)
              } else {
                let labels = {}
                for (let i = 1; i <= 8; i++) {
                  labels['a' + i] = this.form['a' + i]
                  labels['b' + i] = this.form['b' + i]
                }
                this.form.labels = JSON.stringify(labels)
              }
              updateAnnotationAttributes(this.form).then((response) => {
                if (response.code === 200) {
                  this.msgSuccess('修改成功')
                  this.removeCache(this.fileList[this.currentIndex].mQaResultId)
                  this.changePage(0)
                  this.resetUpdateForm()
                } else {
                  this.msgError(response.msg)
                  this.resetUpdateForm()
                }
              })
            }
          }
        })
      },
      cancelUpdateForm() {
        if (this.form.callback) {
          const params = {
            form: this.form,
            ret: 'cancel',
          }
          this.form.callback(params)
        }
        this.resetUpdateForm()
      },
      resetUpdateForm() {
        this.annotationInfoDialogOpen = false
        this.form = {
          mMarkAnnotationId: undefined,
          name: undefined,
          a1: undefined,
          a2: undefined,
          a3: undefined,
          a4: undefined,
          a5: undefined,
          a6: undefined,
          a7: undefined,
          a8: undefined,
          b1: undefined,
          b2: undefined,
          b3: undefined,
          b4: undefined,
          b5: undefined,
          b6: undefined,
          b7: undefined,
          b8: undefined,
        }
        this.resetForm('form')
      },
      //图片格式转换
      dataURLToBlob(dataurl) {
        let arr = dataurl.split(',')
        let mime = arr[0].match(/:(.*?);/)[1]
        let bstr = atob(arr[1])
        let n = bstr.length
        let u8arr = new Uint8Array(n)
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n)
        }
        return new Blob([u8arr], {type: mime})
      },
      saveImage(divText, imgText) {
        let canvasID = this.$refs[divText]
        // let that = this;
        // let a = document.createElement('a');
        html2canvas(canvasID).then((canvas) => {
          // let dom = document.body.appendChild(canvas);
          // dom.style.display = 'none';
          // a.style.display = 'none';
          // document.body.removeChild(dom);
          // let blob = that.dataURLToBlob(dom.toDataURL('image/png'));
          // let url = URL.createObjectURL(blob);
          this.encoder.add(canvas)
          // a.setAttribute('href', url);
          // //这块是保存图片操作  可以设置保存的图片的信息
          // a.setAttribute('download', imgText + '.png');
          // document.body.appendChild(a);
          // a.click();
          // URL.revokeObjectURL(blob);
          // document.body.removeChild(a);
        })
      },
      queryAnnotationList() {
        this.annotationQueryParams.mQaResultId = this.fileList[this.currentIndex].mQaResultId
        annotationList(this.annotationQueryParams).then((res) => {
          if (res.code == '200') {
            res.rows.forEach((row) => {
              if (row.labels) {
                try {
                  const labelsJson = JSON.parse(row.labels)
                  for (let i = 1; i <= 8; i++) {
                    row['a' + i] = labelsJson['a' + i]
                    row['b' + i] = labelsJson['b' + i]
                  }
                } catch {
                }
              }
            })
            this.annotationTotal = res.total
            this.annotationList = res.rows
            this.annotation3dList = []
            res.rows.forEach((row) => {
              if (row.fileType === '3d') this.annotation3dList.push(row)
            })
            // this.annotationDialogVisible = true
          } else {
            this.msgError(res.msg)
          }
        })
      },
      handleAnnotationUpdate(row) {
        this.form.applyFullTask = false
        this.form.applyFollowResult = false
        this.form.mMarkAnnotationId = row.mMarkAnnotationId
        this.form.mQaResultId = row.mQaResultId
        this.form.fileType = row.fileType
        this.selectedObject.type = row.fileType
        this.form.fileName = row.fileName

        let labelTypeName = row.annotationType + '_labelName'
        this.formOptionsInit(row.annotationType + '_', row.name)
        if (this.selectDictLabel(this.attributeNames, labelTypeName)) {
          this.formOptions.name = JSON.parse(this.selectDictLabel(this.attributeNames, labelTypeName)).values
        }
        this.form.name = row.name
        if (row.labels) {
          try {
            const attributesJson = JSON.parse(row.labels)
            for (let i = 1; i <= 8; i++) {
              this.form['a' + i] = attributesJson['a' + i]
            }
            for (let i = 1; i <= 8; i++) {
              this.form['b' + i] = attributesJson['b' + i]
            }
            this.form.labels = attributesJson
          } catch {
            console.log(row.labels, 'parse error')
            for (let i = 1; i <= 8; i++) {
              this.form['a' + i] = row['a' + i]
            }
            for (let i = 1; i <= 8; i++) {
              this.form['b' + i] = null
            }
          }
        } else {
          for (let i = 1; i <= 8; i++) {
            this.form['a' + i] = row['a' + i]
          }
          for (let i = 1; i <= 8; i++) {
            this.form['b' + i] = null
          }
        }
        this.form.callback = (params) => {
          if (params.ret === 'confirm') {
            this.annotationDialogVisible = false
          }
        }
        this.annotationInfoDialogOpen = true
      },
      handleAnnotationDelete(row) {
        this.$confirm('该操作将删除选中的记录，且不可恢复。确定删除?', '警告', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning',
        })
          .then(() => {
            const mMarkAnnotationIds = row.mMarkAnnotationId || this.ids
            deleteAnnotation(mMarkAnnotationIds).then((res) => {
              if (res.code == '200') {
                this.msgSuccess(res.msg)
                annotationList(this.annotationQueryParams).then((res) => {
                  if (res.code == '200') {
                    this.annotationList = res.rows
                    this.annotation3dList = []
                    res.rows.forEach((row) => {
                      if (row.fileType === '3d') this.annotation3dList.push(row)
                    })
                  }
                })
                this.removeCache(this.fileList[this.currentIndex].mQaResultId)
                this.changePage(0)
              } else {
                this.msgError(res.msg)
              }
            })
          })
          .catch(() => {
          })
      },
      annotationNameFormatter(row) {
        let keyName = 'labelName'
        if (this.selectDictLabel(this.attributeNames, row.name + '_labelName')) {
          keyName = row.name + '_labelName'
        } else if (this.selectDictLabel(this.attributeNames, row.annotationType + '_labelName')) {
          keyName = row.annotationType + '_labelName'
        }

        if (this.selectDictLabel(this.attributeNames, keyName)) {
          let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, keyName))
          if (jsonObject.values.hasOwnProperty(row.name)) {
            return jsonObject.values[row.name]
          }
        }
        return row.name
      },
      annotationAttributeFormatter(row, col) {
        const an = col.property + '_' + row.fileType
        const anName = row.name + '_' + an
        const anType = row.annotationType + '_' + an
        try {
          const jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, anName))
          if (jsonObject.values.hasOwnProperty(row[col.property])) return jsonObject.values[row[col.property]]
        } catch {
        }
        try {
          const jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, anType))
          if (jsonObject.values.hasOwnProperty(row[col.property])) return jsonObject.values[row[col.property]]
        } catch {
        }
        try {
          const jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, an))
          if (jsonObject.values.hasOwnProperty(row[col.property])) return jsonObject.values[row[col.property]]
        } catch {
        }
        return row[col.property]
      },
      handleSelectionChange(selection) {
        this.multiple = !selection.length
        this.ids = selection.map((item) => item.mMarkAnnotationId)
        this.$refs.pictureList.showMarkAnnotations(this.ids)
        if (this.markType !== 10) this.$refs.pointCloud.showMarkAnnotations(this.ids)
      },
      annotationNameChanged(value) {
        for (let j = 2; j <= 3; j++) {
          for (let i = 1; i <= 8; i++) {
            let tmp = this.selectDictLabel(this.attributeNames, value + '_a' + i + '_' + j + 'd')
            let markType = this.form.z ? this.form.z : this.selectedObject.markType
            let markTypeAttr = this.selectDictLabel(this.attributeNames, markType + '_a' + i + '_' + j + 'd')
            let traditional = this.selectDictLabel(this.attributeNames, 'a' + i + '_' + j + 'd')
            if (tmp) {
              try {
                this.formOptions['a' + i + '_' + j + 'd'] = JSON.parse(tmp).values
                this.formOptions['a' + i + '_' + j + 'd_description'] = JSON.parse(tmp).typeDesc
                this.labelRules['a' + i] = [{required: true, trigger: 'blur', message: '不能为空'}]
              } catch {
              }
            } else if (markTypeAttr) {
              try {
                this.formOptions['a' + i + '_' + j + 'd'] = JSON.parse(markTypeAttr).values
                this.formOptions['a' + i + '_' + j + 'd_description'] = JSON.parse(markTypeAttr).typeDesc
                this.labelRules['a' + i] = [{required: true, trigger: 'blur', message: '不能为空'}]
              } catch {
              }
            } else if (traditional) {
              try {
                this.formOptions['a' + i + '_' + j + 'd'] = JSON.parse(traditional).values
                this.formOptions['a' + i + '_' + j + 'd_description'] = JSON.parse(traditional).typeDesc
                this.labelRules['a' + i] = [{required: true, trigger: 'blur', message: '不能为空'}]
              } catch {
              }
            } else {
              this.formOptions['a' + i + '_' + j + 'd'] = null
              this.formOptions['a' + i + '_' + j + 'd_description'] = null
            }
          }

          for (let i = 1; i <= 8; i++) {
            let tmp = this.selectDictLabel(this.attributeNames, value + '_b' + i + '_' + j + 'd')
            let markType = this.form.z ? this.form.z : this.selectedObject.markType
            let markTypeAttr = this.selectDictLabel(this.attributeNames, markType + '_b' + i + '_' + j + 'd')
            let traditional = this.selectDictLabel(this.attributeNames, 'b' + i + '_' + j + 'd')
            if (tmp) {
              try {
                this.formOptions['b' + i + '_' + j + 'd'] = JSON.parse(tmp).values
                this.formOptions['b' + i + '_' + j + 'd_description'] = JSON.parse(tmp).typeDesc
                this.labelRules['b' + i] = [{required: true, trigger: 'blur', message: '不能为空'}]
              } catch {
              }
            } else if (markTypeAttr) {
              try {
                this.formOptions['b' + i + '_' + j + 'd'] = JSON.parse(markTypeAttr).values
                this.formOptions['b' + i + '_' + j + 'd_description'] = JSON.parse(markTypeAttr).typeDesc
                this.labelRules['b' + i] = [{required: true, trigger: 'blur', message: '不能为空'}]
              } catch {
              }
            } else if (traditional) {
              try {
                this.formOptions['b' + i + '_' + j + 'd'] = JSON.parse(traditional).values
                this.formOptions['b' + i + '_' + j + 'd_description'] = JSON.parse(traditional).typeDesc
                this.labelRules['b' + i] = [{required: true, trigger: 'blur', message: '不能为空'}]
              } catch {
              }
            } else {
              this.formOptions['b' + i + '_' + j + 'd'] = null
              this.formOptions['b' + i + '_' + j + 'd_description'] = null
            }
          }
        }
      },
      onAnnotationRowSelect(row, column, event) {
        if (row.fileType === '3d') {
          this.$refs.pointCloud.focusObject(row)
        }
      },
      getLabelName(dictValue) {
        let ret = dictValue
        try {
          let jsonObject = JSON.parse(this.selectDictLabel(this.attributeNames, 'labelName'))
          ret = jsonObject.values[ret]
        } catch {
        }
        return ret
      },
      copyPreviousAnnotation() {
        if (this.currentIndex > 0) {
          copyPreviousAnnotation(
            this.fileList[this.currentIndex - 1].mQaResultId,
            this.fileList[this.currentIndex].mQaResultId
          ).then((ret) => {
            if (ret.code == 200) {
              this.removeCache(this.fileList[this.currentIndex].mQaResultId)
              this.changePage(0)
              this.msgSuccess(ret.msg)
            } else {
              this.msgError(ret.msg)
            }
          })
        }
      },
      radioClickitem(key, attribute) {
        if (this.form[attribute] === key) {
          this.form[attribute] = null
        } else {
          this.form[attribute] = key
        }
      },
      imageProjection(cameras, color, assets) {
        const map = new Map()
        cameras.forEach((ret, camera) => {
          const cameraFile = this.fileList[this.currentIndex].fileId.replace('.pcd', '_' + camera + '.jpg')
          map.set(cameraFile, ret)
        })
        this.$refs.pictureList.imageProjection(map, color, assets)
      },
      enterEditPage() {
        window.location.href =
          'http://www.label-data.com/segment/edit/' + this.queryParams.taskId + '/' + this.queryParams.mQaResultId
      },
    },
    // 捕获界面刷新事件，清除标注结果缓存
    beforeRouteEnter(to, from, next) {
      next((vm) => {
        if (from.name === null) {
          vm.removeAnnotationCache('MA:' + to.query.mQaResultId)
        }
      })
    },
    created() {
      this.encoder = new window.Whammy.Video(5)
      if (!this.$route.query.taskId || !this.$route.query.mQaResultId) this.$router.go(-1)
      this.queryParams.taskId = this.$route.query.taskId
      this.queryParams.mQaResultId = this.$route.query.mQaResultId
      this.selectedObjectA1 = this.$route.query.selectedObjectA1
      window.addEventListener('contextmenu', this.contextmenuHandler, true)
      this.$store.dispatch('app/closeSideBar', {withoutAnimation: true})
      this.getDicts('mark_result_error_type').then((response) => {
        this.errorTypeOptions = response.data
      })

      //在页面刷新时将paperToolPosition的信息保存到store里，再由全局main.js保存到localStorage里
      window.addEventListener(
        'beforeunload',
        () => {
          if (this.$refs.pointCloud) {
            this.$refs.pointCloud.autoSave()
          }
          localStorage.setItem('currentIndex', this.currentIndex)
          if (document.getElementById('image-view')) {
            Cookies.set('imageViewSize', document.getElementById('image-view').style.width, {expires: 30})
          }
        },
        true
      )
    },
    mounted() {
      this.qaTaskQuery()
      // this.queryAnnotationList();
      window.addEventListener('resize', this.onWindowResize, true)
      document.addEventListener('keydown', this.keyDownHandler, true)
      document.addEventListener('keyup', this.keyupHandler, true)
      screenfull.on('change', () => {
        this.isFullscreen = screenfull.isFullscreen
      })
    },
    beforeDestroy() {
      Cookies.set('imageViewSize', document.getElementById('image-view').style.width, {expires: 30})
      this.cacheStatusVersion = 0
      this.cacheStatus = {
        taskId: null,
        cacheIndex: 0,
      }
      cancelAnimationFrame(this.animationFrameId)
      window.removeEventListener('contextmenu', this.contextmenuHandler, true)
      window.removeEventListener('resize', this.onWindowResize, true)
      document.removeEventListener('keydown', this.keyDownHandler, true)
      document.removeEventListener('keyup', this.keyupHandler, true)
    },
  }
</script>

<style lang="scss" scoped>
  html,
  body {
    width: 100%;
    height: 100%;
  }

  /* Scale canvas with resize attribute to full size */
  canvas[resize] {
    width: 100%;
    height: auto;
  }

  .special_focus_toolTip {
    z-index: 7;
    position: absolute;
    display: none;
    width: 180px;
    height: 240px;
    border-style: solid;
    transition: left 0.4s cubic-bezier(0.23, 1, 0.32, 1), top 0.4s cubic-bezier(0.23, 1, 0.32, 1);
    background-color: rgba(50, 50, 50, 0.701961);
    border-width: 0px;
    border-color: #333333;
    border-radius: 4px;
    color: #ffffff;
    font-style: normal;
    font-variant: normal;
    font-weight: normal;
    font-stretch: normal;
    font-size: 14px;
    font-family: 'Microsoft YaHei';
    line-height: 21px;
    padding: 10px 10px;
    pointer-events: none;
  }

  .icon-list {
    height: calc(100vh - 155px);
    overflow-y: auto;

    .color-name {
      height: 30px;
      line-height: 30px;
      // margin-bottom: -5px;
      cursor: pointer;
      width: 50%;
      float: left;

      span {
        vertical-align: 0.3em;
        fill: currentColor;
        margin-left: 5px;
      }
    }
  }

  .bottom-div {
    bottom: 0;
    height: 46px;
    line-height: 46px;
    padding: 0 10px;
    background: #fff;

    .el-form-item {
      margin: 0;
      display: inline-grid;
      vertical-align: middle;
    }

    .filename {
      word-wrap: break-word;
      word-break: break-all;
      display: flex;
      align-items: center;
      height: 46px;

      span {
        line-height: 18px;
      }
    }

    .color-name-btn {
      display: flex;
      align-items: center;
      height: 46px;
      margin-left: 15px;
    }
  }

  /*  dialog*/
  .el-dialog__header {
    padding: 15px 20px 15px;
  }

  .el-dialog__headerbtn {
    top: 15px;
  }

  /*dialog header*/
  .el-dialog__header {
    background: #e3eaed;
  }

  .avue-crud__dialog__header {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    -webkit-box-pack: justify;
    -ms-flex-pack: justify;
    justify-content: space-between;
  }

  .el-dialog__title {
    color: rgba(0, 0, 0, 0.85);
    font-weight: 500;
    word-wrap: break-word;
  }

  .avue-crud__dialog__menu {
    padding-right: 20px;
    float: left;
  }

  .avue-crud__dialog__menu i {
    color: #909399;
    font-size: 15px;
  }

  .el-icon-full-screen {
    cursor: pointer;
  }

  .el-icon-full-screen:before {
    content: '\e719';
  }

  #image-view {
    position: absolute;
    top: 0%;
    left: 0%;
    width: 30%;
    max-width: 40%;
    min-width: 20%;
    resize: horizontal;
    border-width: 0px;
    overflow: auto;
    z-index: 100;
  }
</style>
